import json
import os
import zipfile
from datetime import datetime
import xml.etree.ElementTree as ET

import requests
from loguru import logger

from dto.meituan_one_way_policy_request import *


# -*- coding: utf-8 -*-
# @Author : HJH
# @Time : 2024/1/23 10:19
# @Use : 美团上传单程预付政策

def mt_process_row(row, pr_param):
    """
    定义一个函数，传入一行数据，转化为Policy需要导入的政策
    :param pr_param: 输入的参数
    :param row:携程数据
    :return:美团接口需要的Policy数据
    """
    if not isinstance(pr_param, dict):
        RuntimeError("输入参数有误，请检查后重新启动")

    policy = Policy()
    # 航空公司
    policy.flightcode = str(row.get('flightNo')[:2])
    # 政策标识
    policy.policyCode = pr_param.get('policyCode').replace("*", "")
    # 根据仓位设置政策标识
    if pr_param.get('policy_of_cabin') == 1:
        if row.get('cabin') in 'N,T,Z,V,E,H,U,L,A,M,B,Y':
            policy.policyCode = (pr_param.get('policyCode') + '0').replace("*", "")
        elif row.get('cabin') in 'R':
            policy.policyCode = (pr_param.get('policyCode') + '1').replace("*", "")
    # 起飞机场
    policy.dpt = row.get('dep')
    # 到达机场
    policy.arr = row.get('arr')
    # 航班限制
    policy.flightNumLimit = '适用'
    # 航班号
    policy.flightcondition = row.get('flightNo')
    # 旅行班期
    policy.daycondition = '1234567'
    # 舱位
    policy.cabin = row.get('cabin')
    # 票面价类型
    policy.discountType = '1'
    # 票面价/折扣
    policy.discountValue = str(int(float(row.get('costPrice'))) + pr_param.get('discountValueAdd', 0))
    # 返点
    policy.returnpoint = '0'
    # 返点计算模式
    policy.returnPointCalMode = '1'
    # 留钱
    policy.returnprice = pr_param.get('returnprice')
    # 销售起始日期
    policy.startdate_ticket = datetime.now().strftime("%Y-%m-%d")
    # 销售结束日期
    policy.enddate_ticket = datetime.now().replace(month=12, day=31, hour=23, minute=59,
                                                   second=59).strftime("%Y-%m-%d")
    # 旅行起始日期
    policy.startdate = row.get('depDate')
    # 旅行结束日期
    policy.enddate = row.get('depDate')
    # 最早提前销售天数
    policy.earliestBeforeValidDay = '365'
    # 最晚提前销售天数
    policy.beforeValidDay = pr_param.get('beforeValidDay')
    # 舱位说明
    policy.cabinnote = row.get('price').split('.')[0] + pr_param.get('policy_note')
    # 是否生成 PNR
    policy.needPnr = pr_param.get('needPnr')
    # 紧俏座位具体策略
    policy.pnrStrategy = pr_param.get('pnrStrategy')
    # 紧俏座位阈值
    policy.tightSeatCount = pr_param.get('tightSeatCount')
    # 是否 PATA 验价
    policy.pata = '0'
    # 产品类型
    policy.productTypeList = '72'
    # 追加阈值金额
    policy.discountThreshhold = pr_param.get('discountThreshhold')
    return policy


def add_mt_policy(policies: list):
    """
    单程统一政策上传参数
    :param qp_dom: 域名标识
    :param policies: 政策列表
    :return:
    """
    policy_list = PolicyList()
    # 用户名
    policy_list.username = 'zhengce936'
    # 密码
    policy_list.password = 'qWGjcxSv'
    # 上传类型
    policy_list.execType = 'ADD'
    # 政策类型
    policy_list.type = 'PREPAY'

    root = ET.Element('PolicyList')
    # 转xml请求格式
    for key, value in vars(policy_list).items():
        root.set(key, value)

    for item in policies:
        policy_xml = ET.SubElement(root, 'Policy')
        for key2, value2 in vars(item).items():
            policy_xml.set(key2, value2)

    xml_data = ET.tostring(root, encoding='utf-8', xml_declaration=True).decode('utf-8')
    # print(xml_data)
    return xml_data


def del_mt_policy(del_p_c, del_p_list):
    """
    单程统一政策删除参数
    :param del_p_list: 需要删除的政策，为空表示根据政策代码全删除
    :param del_p_c: 需要删除政策代码
    :return:
    """
    policy_list = PolicyList()
    # 用户名
    policy_list.username = 'zhengce936'
    # 密码
    policy_list.password = 'qWGjcxSv'
    # 上传类型
    policy_list.execType = 'ADD'
    # 政策类型
    policy_list.type = 'PREPAY'

    root = ET.Element('PolicyList')
    for key, value in vars(policy_list).items():
        root.set(key, value)

    if del_p_list is not None:
        for del_p in del_p_list:
            # 删除政策参数
            delete_policy = DeletePolicy()
            # 政策类型
            delete_policy.type = 'PREPAY'
            # 政策标识
            delete_policy.policyCode = del_p_c
            # 航空公司
            # delete_policy.flightcode = del_p.get('flightNo')[:2]
            # 出发地
            delete_policy.dpt = del_p.get('dep')
            # 目的地
            delete_policy.arr = del_p.get('arr')
            # 舱位
            # delete_policy.cabin = del_p.get('cabin')
            # 旅行起始日期
            delete_policy.startdate = del_p.get('depDate')
            # 旅行结束日期
            delete_policy.enddate = del_p.get('depDate')

            del_policy_xml = ET.SubElement(root, 'DeletePolicy')
            for key, value in vars(delete_policy).items():
                del_policy_xml.set(key, value if value is not None else '')
    else:
        # 删除政策参数
        delete_policy = DeletePolicy()
        # 政策类型
        delete_policy.type = 'PREPAY'
        # 政策标识
        delete_policy.policyCode = del_p_c
        del_policy_xml = ET.SubElement(root, 'DeletePolicy')
        for key, value in vars(delete_policy).items():
            del_policy_xml.set(key, value if value is not None else '')

    xml_data = ET.tostring(root, encoding='utf-8', xml_declaration=True).decode('utf-8')
    # print(xml_data)
    return xml_data


def send_mt_request(xml_params):
    # 1. 创建临时的 XML 文件并写入 xml_data
    xml_filename = "mt_policy.xml"  # XML 文件名
    zip_filename = "mt_policy.zip"  # ZIP 文件名
    with open(xml_filename, "w", encoding="utf-8") as file:
        file.write(xml_params)

    # 2. 创建一个空的 ZIP 文件
    with zipfile.ZipFile(zip_filename, "w") as zip_file:
        # 3. 将 XML 文件添加到 ZIP 文件中
        zip_file.write(xml_filename)

    # 4. 删除临时 XML 文件
    os.remove(xml_filename)

    url = "https://mproxy-flight.meituan.com/exinterface/post/policies/batch/xml/"

    # 使用 requests 发送 POST 请求并上传 ZIP 文件
    payload = {'siteno': '936'}
    files = [
        ('uploadfile', ('file', open(zip_filename, "rb"), 'application/octet-stream'))
    ]
    headers = {}

    # 发送POST请求并上传文件
    response = requests.request("POST", url, headers=headers, data=payload, files=files)
    # logger.info("【美团请求结果】: {}", response.text)
    if response.status_code != 200:
        logger.error("【美团请求异常】: {}", response.text)


def run_mt_upload(ru_xc_res, ru_param):
    if not isinstance(ru_param, dict):
        RuntimeError("输入参数有误，请检查后重新启动")

    policyDtoList = []
    for item in ru_xc_res:
        # 根据舱位复制
        if ru_param.get('copy_of_cabin', None) is not None:
            cabins = ru_param.get('copy_of_cabin').split(',')
            for cabin in cabins:
                item['cabin'] = cabin
                policyDto = mt_process_row(item, ru_param)
                policyDtoList.append(policyDto)
        else:
            policyDto = mt_process_row(item, ru_param)
            policyDtoList.append(policyDto)

    size = 10000
    total = len(policyDtoList)
    logger.info(f"【上传{ru_param.get('platform')}政策数据长度】: {total}")
    if total == 0:
        return
    logger.info(f"【美团单程预付上传政策】: 请求中... ...")
    for i in range(0, total, size):
        # 取出最大450条数据，添加到结果列表
        end = i + size
        subset = policyDtoList[i:end]
        # 获取请求参数
        add_req = add_mt_policy(subset)
        send_mt_request(add_req)

    logger.info(f"【美团单程预付政策上传成功】: {ru_param.get('policyCode')}")
